/**
 * 类型转换工具模块
 * 提供各种数据类型转换功能，包括基本类型转换、单位转换、进制转换等
 */

/**
 * 转换为字符串
 * @param {*} value 要转换的值
 * @param {*} defaultValue 默认值
 * @returns {string} 转换后的字符串
 */
export function toString(value, defaultValue = '') {
  if (value === null || value === undefined) {
    return defaultValue;
  }
  return String(value);
}

/**
 * 转换为数字
 * @param {*} value 要转换的值
 * @param {number} defaultValue 默认值
 * @returns {number} 转换后的数字
 */
export function toNumber(value, defaultValue = 0) {
  if (value === null || value === undefined || value === '') {
    return defaultValue;
  }

  const num = Number(value);
  return isNaN(num) ? defaultValue : num;
}

/**
 * 转换为整数
 * @param {*} value 要转换的值
 * @param {number} defaultValue 默认值
 * @returns {number} 转换后的整数
 */
export function toInteger(value, defaultValue = 0) {
  const num = toNumber(value, defaultValue);
  return Math.floor(num);
}

/**
 * 转换为浮点数
 * @param {*} value 要转换的值
 * @param {number} precision 小数位数
 * @param {number} defaultValue 默认值
 * @returns {number} 转换后的浮点数
 */
export function toFloat(value, precision = 2, defaultValue = 0) {
  const num = toNumber(value, defaultValue);
  return parseFloat(num.toFixed(precision));
}

/**
 * 转换为布尔值
 * @param {*} value 要转换的值
 * @param {boolean} defaultValue 默认值
 * @returns {boolean} 转换后的布尔值
 */
export function toBoolean(value, defaultValue = false) {
  if (value === null || value === undefined) {
    return defaultValue;
  }

  if (typeof value === 'boolean') {
    return value;
  }

  if (typeof value === 'string') {
    const lower = value.toLowerCase();
    return ['true', '1', 'yes', 'on'].includes(lower);
  }

  if (typeof value === 'number') {
    return value !== 0;
  }

  return Boolean(value);
}

/**
 * 转换为数组
 * @param {*} value 要转换的值
 * @param {Array} defaultValue 默认值
 * @returns {Array} 转换后的数组
 */
export function toArray(value, defaultValue = []) {
  if (value === null || value === undefined) {
    return defaultValue;
  }

  if (Array.isArray(value)) {
    return value;
  }

  if (typeof value === 'string') {
    try {
      const parsed = JSON.parse(value);
      return Array.isArray(parsed) ? parsed : [value];
    } catch (e) {
      return value.split(',').map(item => item.trim());
    }
  }

  if (typeof value === 'object' && value[Symbol.iterator]) {
    return Array.from(value);
  }

  return [value];
}

/**
 * 转换为对象
 * @param {*} value 要转换的值
 * @param {Object} defaultValue 默认值
 * @returns {Object} 转换后的对象
 */
export function toObject(value, defaultValue = {}) {
  if (value === null || value === undefined) {
    return defaultValue;
  }

  if (typeof value === 'object' && !Array.isArray(value)) {
    return value;
  }

  if (typeof value === 'string') {
    try {
      const parsed = JSON.parse(value);
      return typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : defaultValue;
    } catch (e) {
      return defaultValue;
    }
  }

  return defaultValue;
}

/**
 * 转换为日期
 * @param {*} value 要转换的值
 * @param {Date} defaultValue 默认值
 * @returns {Date} 转换后的日期
 */
export function toDate(value, defaultValue = new Date()) {
  if (value === null || value === undefined) {
    return defaultValue;
  }

  if (value instanceof Date) {
    return isNaN(value.getTime()) ? defaultValue : value;
  }

  const date = new Date(value);
  return isNaN(date.getTime()) ? defaultValue : date;
}

/**
 * 十进制转二进制
 * @param {number} decimal 十进制数
 * @returns {string} 二进制字符串
 */
export function decimalToBinary(decimal) {
  const num = toInteger(decimal);
  return num.toString(2);
}

/**
 * 二进制转十进制
 * @param {string} binary 二进制字符串
 * @returns {number} 十进制数
 */
export function binaryToDecimal(binary) {
  return parseInt(binary, 2);
}

/**
 * 十进制转八进制
 * @param {number} decimal 十进制数
 * @returns {string} 八进制字符串
 */
export function decimalToOctal(decimal) {
  const num = toInteger(decimal);
  return num.toString(8);
}

/**
 * 八进制转十进制
 * @param {string} octal 八进制字符串
 * @returns {number} 十进制数
 */
export function octalToDecimal(octal) {
  return parseInt(octal, 8);
}

/**
 * 十进制转十六进制
 * @param {number} decimal 十进制数
 * @param {boolean} uppercase 是否大写
 * @returns {string} 十六进制字符串
 */
export function decimalToHex(decimal, uppercase = false) {
  const num = toInteger(decimal);
  const hex = num.toString(16);
  return uppercase ? hex.toUpperCase() : hex;
}

/**
 * 十六进制转十进制
 * @param {string} hex 十六进制字符串
 * @returns {number} 十进制数
 */
export function hexToDecimal(hex) {
  return parseInt(hex, 16);
}

/**
 * RGB转HEX
 * @param {number} r 红色值 (0-255)
 * @param {number} g 绿色值 (0-255)
 * @param {number} b 蓝色值 (0-255)
 * @returns {string} HEX颜色值
 */
export function rgbToHex(r, g, b) {
  const toHex = (value) => {
    const hex = Math.max(0, Math.min(255, Math.round(value))).toString(16);
    return hex.length === 1 ? '0' + hex : hex;
  };

  return '#' + toHex(r) + toHex(g) + toHex(b);
}

/**
 * HEX转RGB
 * @param {string} hex HEX颜色值
 * @returns {Object} RGB对象 {r, g, b}
 */
export function hexToRgb(hex) {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}

/**
 * RGB转HSL
 * @param {number} r 红色值 (0-255)
 * @param {number} g 绿色值 (0-255)
 * @param {number} b 蓝色值 (0-255)
 * @returns {Object} HSL对象 {h, s, l}
 */
export function rgbToHsl(r, g, b) {
  r /= 255;
  g /= 255;
  b /= 255;

  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  let h, s, l = (max + min) / 2;

  if (max === min) {
    h = s = 0;
  } else {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

    switch (max) {
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }
    h /= 6;
  }

  return {
    h: Math.round(h * 360),
    s: Math.round(s * 100),
    l: Math.round(l * 100)
  };
}

/**
 * HSL转RGB
 * @param {number} h 色调 (0-360)
 * @param {number} s 饱和度 (0-100)
 * @param {number} l 亮度 (0-100)
 * @returns {Object} RGB对象 {r, g, b}
 */
export function hslToRgb(h, s, l) {
  h /= 360;
  s /= 100;
  l /= 100;

  const hue2rgb = (p, q, t) => {
    if (t < 0) t += 1;
    if (t > 1) t -= 1;
    if (t < 1/6) return p + (q - p) * 6 * t;
    if (t < 1/2) return q;
    if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
    return p;
  };

  let r, g, b;

  if (s === 0) {
    r = g = b = l;
  } else {
    const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    const p = 2 * l - q;
    r = hue2rgb(p, q, h + 1/3);
    g = hue2rgb(p, q, h);
    b = hue2rgb(p, q, h - 1/3);
  }

  return {
    r: Math.round(r * 255),
    g: Math.round(g * 255),
    b: Math.round(b * 255)
  };
}

/**
 * 摄氏度转华氏度
 * @param {number} celsius 摄氏度
 * @returns {number} 华氏度
 */
export function celsiusToFahrenheit(celsius) {
  return (celsius * 9/5) + 32;
}

/**
 * 华氏度转摄氏度
 * @param {number} fahrenheit 华氏度
 * @returns {number} 摄氏度
 */
export function fahrenheitToCelsius(fahrenheit) {
  return (fahrenheit - 32) * 5/9;
}

/**
 * 摄氏度转开尔文
 * @param {number} celsius 摄氏度
 * @returns {number} 开尔文
 */
export function celsiusToKelvin(celsius) {
  return celsius + 273.15;
}

/**
 * 开尔文转摄氏度
 * @param {number} kelvin 开尔文
 * @returns {number} 摄氏度
 */
export function kelvinToCelsius(kelvin) {
  return kelvin - 273.15;
}

/**
 * 米转英尺
 * @param {number} meters 米
 * @returns {number} 英尺
 */
export function metersToFeet(meters) {
  return meters * 3.28084;
}

/**
 * 英尺转米
 * @param {number} feet 英尺
 * @returns {number} 米
 */
export function feetToMeters(feet) {
  return feet / 3.28084;
}

/**
 * 千米转英里
 * @param {number} kilometers 千米
 * @returns {number} 英里
 */
export function kilometersToMiles(kilometers) {
  return kilometers * 0.621371;
}

/**
 * 英里转千米
 * @param {number} miles 英里
 * @returns {number} 千米
 */
export function milesToKilometers(miles) {
  return miles / 0.621371;
}

/**
 * 千克转磅
 * @param {number} kilograms 千克
 * @returns {number} 磅
 */
export function kilogramsToPounds(kilograms) {
  return kilograms * 2.20462;
}

/**
 * 磅转千克
 * @param {number} pounds 磅
 * @returns {number} 千克
 */
export function poundsToKilograms(pounds) {
  return pounds / 2.20462;
}

/**
 * 字节转换
 * @param {number} bytes 字节数
 * @param {number} decimals 小数位数
 * @returns {string} 格式化后的大小
 */
export function bytesToSize(bytes, decimals = 2) {
  if (bytes === 0) return '0 B';

  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];

  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

/**
 * 大小转字节
 * @param {string} size 大小字符串，如 "1.5 MB"
 * @returns {number} 字节数
 */
export function sizeToBytes(size) {
  const units = {
    'B': 1,
    'KB': 1024,
    'MB': 1024 * 1024,
    'GB': 1024 * 1024 * 1024,
    'TB': 1024 * 1024 * 1024 * 1024,
    'PB': 1024 * 1024 * 1024 * 1024 * 1024
  };

  const match = size.match(/^(\d+(?:\.\d+)?)\s*([A-Z]{1,2})$/i);
  if (!match) return 0;

  const value = parseFloat(match[1]);
  const unit = match[2].toUpperCase();

  return value * (units[unit] || 1);
}

/**
 * 角度转弧度
 * @param {number} degrees 角度
 * @returns {number} 弧度
 */
export function degreesToRadians(degrees) {
  return degrees * (Math.PI / 180);
}

/**
 * 弧度转角度
 * @param {number} radians 弧度
 * @returns {number} 角度
 */
export function radiansToDegrees(radians) {
  return radians * (180 / Math.PI);
}

/**
 * 毫秒转换为时间字符串
 * @param {number} milliseconds 毫秒数
 * @param {boolean} includeMs 是否包含毫秒
 * @returns {string} 时间字符串
 */
export function millisecondsToTime(milliseconds, includeMs = false) {
  const totalSeconds = Math.floor(milliseconds / 1000);
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;
  const ms = milliseconds % 1000;

  let result = '';
  if (hours > 0) {
    result += hours.toString().padStart(2, '0') + ':';
  }
  result += minutes.toString().padStart(2, '0') + ':';
  result += seconds.toString().padStart(2, '0');

  if (includeMs) {
    result += '.' + ms.toString().padStart(3, '0');
  }

  return result;
}

/**
 * 时间字符串转毫秒
 * @param {string} timeString 时间字符串，格式：HH:MM:SS 或 MM:SS 或 HH:MM:SS.mmm
 * @returns {number} 毫秒数
 */
export function timeToMilliseconds(timeString) {
  const parts = timeString.split(':');
  let hours = 0, minutes = 0, seconds = 0, milliseconds = 0;

  if (parts.length === 3) {
    hours = parseInt(parts[0]);
    minutes = parseInt(parts[1]);
    const secondParts = parts[2].split('.');
    seconds = parseInt(secondParts[0]);
    if (secondParts[1]) {
      milliseconds = parseInt(secondParts[1].padEnd(3, '0'));
    }
  } else if (parts.length === 2) {
    minutes = parseInt(parts[0]);
    const secondParts = parts[1].split('.');
    seconds = parseInt(secondParts[0]);
    if (secondParts[1]) {
      milliseconds = parseInt(secondParts[1].padEnd(3, '0'));
    }
  }

  return hours * 3600000 + minutes * 60000 + seconds * 1000 + milliseconds;
}

/**
 * 安全类型转换
 * @param {*} value 要转换的值
 * @param {string} type 目标类型
 * @param {*} defaultValue 默认值
 * @returns {*} 转换后的值
 */
export function safeCast(value, type, defaultValue = null) {
  try {
    switch (type.toLowerCase()) {
      case 'string':
        return toString(value, defaultValue);
      case 'number':
        return toNumber(value, defaultValue);
      case 'integer':
      case 'int':
        return toInteger(value, defaultValue);
      case 'float':
        return toFloat(value, 2, defaultValue);
      case 'boolean':
      case 'bool':
        return toBoolean(value, defaultValue);
      case 'array':
        return toArray(value, defaultValue);
      case 'object':
        return toObject(value, defaultValue);
      case 'date':
        return toDate(value, defaultValue);
      default:
        return value;
    }
  } catch (e) {
    return defaultValue;
  }
}